package util

import (
	"bytes"
	"common/logging"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"iot/iot_app_server/proto"
	"net/http"
	//"strconv"
	"strings"
	"time"
)

var (
	ERR_CODE_SUCCESS                             = 0
	ERR_CODE_PARA_ERROR                          = 1001
	ERR_CODE_DB_ERROR                            = 1002
	ERR_CODE_SYSTEM_ERROR                        = 1003
	ERR_CODE_TIMEOUT                             = 1004
	ERR_CODE_SCENE_NOT_EXIST                     = 1005
	ERR_CODE_SCENE_INVALID                       = 1006
	ERR_CODE_DEVICE_NOT_EXIST                    = 1007
	ERR_CODE_DEVICE_EXIST                        = 1008
	ERR_CODE_NOT_YOUR_DEVICE                     = 1009
	ERR_CODE_DEVICE_OFFLINE                      = 1010
	ERR_CODE_INVALID_DEVICE_RESPONSE             = 1011
	ERR_CODE_DEVICE_RESPONSE_CODE                = 1012
	ERR_CODE_DEVICE_PROCESS_ERROR                = 1013
	ERR_CODE_USER_ROLE_IS_ILLEGAL                = 1014
	ERR_CODE_CONF_NOT_EXIST                      = 1015
	ERR_CODE_PUSH_FAILED                         = 1016
	ERR_CODE_GATEWAY_NOT_BOUND_BY_USER           = 1017
	ERR_CODE_GET_SMS_CODE_FAIL                   = 1018
	ERR_CODE_SMS_CODE_ERROR                      = 1019
	ERR_CODE_SMS_CODE_EXPIRED                    = 1020
	ERR_CODE_OPEN_YS_SERVICE_FAIL                = 1021
	ERR_CODE_GET_ACCESS_TOKEN_FAIL               = 1022
	ERR_CODE_USER_NOT_OPEN_YS_SERVICE            = 1023
	ERR_CODE_USER_ALREADY_OPEN_YS_SERVICE        = 1024
	ERR_CODE_GET_SMS_CODE_TOO_OFTEN              = 1025
	ERR_CODE_SMS_CODE_INPUT_ERROR_TIMES_TOO_MANY = 1026

	ERR_CODE_USER_HAS_NO_PERMISSION = 1027
	ERR_CODE_USER_HAS_NO_GATEWAY    = 1028
	ERR_CODE_INVALID_TOPIC          = 1029
	ERR_CODE_PERMISSION_DENIED      = 1030

	ERR_CODE_GATEWAY_TO_APPLIANCE_TRANSPORT_ERROR = 3001

	ERR_STR_SUCCESS                             = "ok"
	ERR_STR_PARA_ERROR                          = "para error"
	ERR_STR_DB_ERROR                            = "db error"
	ERR_STR_SYSTEM_ERROR                        = "system error"
	ERR_STR_TIMEOUT                             = "network timeout"
	ERR_STR_SCENE_NOT_EXIST                     = "scene not exist"
	ERR_STR_SCENE_INVALID                       = "scene invalid"
	ERR_STR_DEVICE_NOT_EXIST                    = "zigbee device not exist"
	ERR_STR_DEVICE_EXIST                        = "zigbee device exist"
	ERR_STR_NOT_YOUR_DEVICE                     = "not your device"
	ERR_STR_DEVICE_OFFLINE                      = "device offline"
	ERR_STR_INVALID_DEVICE_RESPONSE             = "invalid device response"
	ERR_STR_DEVICE_RESPONSE_CODE                = "device response code error"
	ERR_STR_DEVICE_PROCESS_ERROR                = "device process error"
	ERR_STR_USER_ROLE_IS_ILLEGAL                = "user role is illegal"
	ERR_STR_CONF_NOT_EXIST                      = "static conf not exist"
	ERR_STR_GATEWAY_NOT_BOUND_BY_USER           = "gateway not bound by user"
	ERR_STR_GET_SMS_CODE_FAIL                   = "get sms code failed"
	ERR_STR_SMS_CODE_ERROR                      = "sms code error"
	ERR_STR_SMS_CODE_EXPIRED                    = "sms code expired"
	ERR_STR_OPEN_YS_SERVICE_FAIL                = "open ys service failed"
	ERR_STR_GET_ACCESS_TOKEN_FAIL               = "get access token failed"
	ERR_STR_USER_NOT_OPEN_YS_SERVICE            = "user has not opened ys service yet"
	ERR_STR_USER_ALREADY_OPEN_YS_SERVICE        = "user has opened ys service"
	ERR_STR_GET_SMS_CODE_TOO_OFTEN              = "get sms code too often"
	ERR_STR_SMS_CODE_INPUT_ERROR_TIMES_TOO_MANY = "sms code input error times too many"

	ERR_STR_USER_HAS_NO_PERMISSION = "user has no permission"
	ERR_STR_USER_HAS_NO_GATEWAY    = "user has no gateway"
	ERR_STR_INVALID_TOPIC          = "invalid transport topic"
	ERR_STR_PERMISSION_DENIED      = "permission denied "

	ERR_STR_GATEWAY_TO_APPLIANCE_TRANSPORT_ERROR = "gateway to appliance transport error"
	ErrMap                                       = make(map[int]string)
)

//初始化包内的变量，自动执行
func init() {
	ErrMap[ERR_CODE_SUCCESS] = ERR_STR_SUCCESS
	ErrMap[ERR_CODE_PARA_ERROR] = ERR_STR_PARA_ERROR
	ErrMap[ERR_CODE_DB_ERROR] = ERR_STR_DB_ERROR
	ErrMap[ERR_CODE_SYSTEM_ERROR] = ERR_STR_SYSTEM_ERROR
	ErrMap[ERR_CODE_TIMEOUT] = ERR_STR_TIMEOUT
	ErrMap[ERR_CODE_SCENE_NOT_EXIST] = ERR_STR_SCENE_NOT_EXIST
	ErrMap[ERR_CODE_SCENE_INVALID] = ERR_STR_SCENE_INVALID
	ErrMap[ERR_CODE_DEVICE_NOT_EXIST] = ERR_STR_DEVICE_NOT_EXIST
	ErrMap[ERR_CODE_DEVICE_EXIST] = ERR_STR_DEVICE_EXIST
	ErrMap[ERR_CODE_NOT_YOUR_DEVICE] = ERR_STR_NOT_YOUR_DEVICE
	ErrMap[ERR_CODE_DEVICE_OFFLINE] = ERR_STR_DEVICE_OFFLINE
	ErrMap[ERR_CODE_INVALID_DEVICE_RESPONSE] = ERR_STR_INVALID_DEVICE_RESPONSE
	ErrMap[ERR_CODE_DEVICE_RESPONSE_CODE] = ERR_STR_DEVICE_RESPONSE_CODE
	ErrMap[ERR_CODE_DEVICE_PROCESS_ERROR] = ERR_STR_DEVICE_PROCESS_ERROR
	ErrMap[ERR_CODE_USER_ROLE_IS_ILLEGAL] = ERR_STR_USER_ROLE_IS_ILLEGAL
	ErrMap[ERR_CODE_CONF_NOT_EXIST] = ERR_STR_CONF_NOT_EXIST
	ErrMap[ERR_CODE_GATEWAY_NOT_BOUND_BY_USER] = ERR_STR_GATEWAY_NOT_BOUND_BY_USER
	ErrMap[ERR_CODE_GET_SMS_CODE_FAIL] = ERR_STR_GET_SMS_CODE_FAIL
	ErrMap[ERR_CODE_SMS_CODE_ERROR] = ERR_STR_SMS_CODE_ERROR
	ErrMap[ERR_CODE_SMS_CODE_EXPIRED] = ERR_STR_SMS_CODE_EXPIRED
	ErrMap[ERR_CODE_OPEN_YS_SERVICE_FAIL] = ERR_STR_OPEN_YS_SERVICE_FAIL
	ErrMap[ERR_CODE_GET_ACCESS_TOKEN_FAIL] = ERR_STR_GET_ACCESS_TOKEN_FAIL
	ErrMap[ERR_CODE_USER_NOT_OPEN_YS_SERVICE] = ERR_STR_USER_NOT_OPEN_YS_SERVICE
	ErrMap[ERR_CODE_USER_ALREADY_OPEN_YS_SERVICE] = ERR_STR_USER_ALREADY_OPEN_YS_SERVICE
	ErrMap[ERR_CODE_GET_SMS_CODE_TOO_OFTEN] = ERR_STR_GET_SMS_CODE_TOO_OFTEN
	ErrMap[ERR_CODE_SMS_CODE_INPUT_ERROR_TIMES_TOO_MANY] = ERR_STR_SMS_CODE_INPUT_ERROR_TIMES_TOO_MANY

	ErrMap[ERR_CODE_USER_HAS_NO_PERMISSION] = ERR_STR_USER_HAS_NO_PERMISSION
	ErrMap[ERR_CODE_USER_HAS_NO_GATEWAY] = ERR_STR_USER_HAS_NO_GATEWAY

	ErrMap[ERR_CODE_GATEWAY_TO_APPLIANCE_TRANSPORT_ERROR] = ERR_STR_GATEWAY_TO_APPLIANCE_TRANSPORT_ERROR
	ErrMap[ERR_CODE_INVALID_TOPIC] = ERR_STR_INVALID_TOPIC
	ErrMap[ERR_CODE_PERMISSION_DENIED] = ERR_STR_PERMISSION_DENIED
}

//按统一格式生成http回复
//{
//   "errorCode":0,
//   "msg":"ok",
//   "msgid":"xxxxx",
//   "data":{
//   }
//}
//参数说明：
//msg支持变参
//data支持任何对象，注意如果data是struct，struct内部只有公有成员能正常Marshal,若json的key首字母小写需使用tag来解决
type HttpResponseData struct {
	Code  int         `json:"code"`
	Msgid string      `json:"msgid"`
	Msg   string      `json:"msg"`
	Data  interface{} `json:"data"`
}

type LogRequestInfo struct {
	Method string
	URL    string
	Form   interface{}
	Body   interface{}
}

func LogGetResponseString_PB(req *MSGBUS_DOWNSTREAM.MqttPub, stime time.Time, msgid string, code int, data interface{}, msg ...interface{}) []byte {
	ret := GetResponseString(msgid, code, data, msg...)

	use_time := time.Now().Sub(stime)
	logging.Info("HANDLE_LOG_PB:uri=%s,use_time=%v,request=%+v,response=%s", req.GetTopic(), use_time, req, string(ret))
	return ret
}

func LogGetResponseString_EX(req *http.Request, stime time.Time, msgid string, extra map[string]interface{}, code int, data interface{}, msg ...interface{}) []byte {
	ret := GetResponseString(msgid, code, data, msg...)
	retMap := &map[string]interface{}{}
	json.Unmarshal(ret, retMap)
	for k, v := range extra {
		(*retMap)[k] = v
	}
	response, _ := json.Marshal(retMap)

	defer req.Body.Close()
	body := ""
	b_body, err := ioutil.ReadAll(req.Body)
	if err == nil {
		body = string(b_body)
	}

	logReq := LogRequestInfo{
		Method: req.Method,
		URL:    req.RequestURI,
		Form:   req.Form,
		Body:   body,
	}

	use_time := time.Now().Sub(stime)
	logging.Info("HANDLE_LOG:uri=%s,use_time=%v,request=%+v,response=%s", req.RequestURI, use_time, logReq, string(response))
	return response
}

func LogGetResponseString(req *http.Request, stime time.Time, msgid string, code int, data interface{}, msg ...interface{}) []byte {
	ret := GetResponseString(msgid, code, data, msg...)
	defer req.Body.Close()

	body := ""
	b_body, err := ioutil.ReadAll(req.Body)
	if err == nil {
		body = string(b_body)
	}

	logReq := LogRequestInfo{
		Method: req.Method,
		URL:    req.RequestURI,
		Form:   req.Form,
		Body:   body,
	}
	use_time := time.Now().Sub(stime)
	logging.Info("HANDLE_LOG:uri=%s,use_time=%v,request=%+v,response=%s", req.RequestURI, use_time, logReq, string(ret))
	return ret
}

func GetResponseString(msgid string, code int, data interface{}, msg ...interface{}) []byte {
	response := &HttpResponseData{
		Code:  code,
		Data:  data,
		Msgid: msgid,
	}

	msgfmt, exist := ErrMap[code]
	if !exist { //找不到说明代码有错误，panic
		logging.Error("GetResponseString failed errorcode:%d not exist", code)
		msgfmt = ""
		//panic("GetResponseString failed errorcode:" + strconv.Itoa(code) + " not exist")
	}
	var msginfo = msgfmt
	if len(msg) != 0 {

		msginfo = fmt.Sprintf(msgfmt, msg...)
	}
	response.Msg = msginfo

	//logging.Debug("response=%+v", response)
	//return []byte("")
	ret, err := json.Marshal(response)
	if err != nil {
		logging.Error("GetResponseString failed,code=%d,data=%v,msg=%v, err=%s", code, data, msg, err.Error())
		//panic("GetResponseString failed, " + "code=" + strconv.Itoa(code) + err.Error())
		return []byte("")
	}

	return ret
}

//POST请求时json反解用
func GetReqBody(req *http.Request, info interface{}) (interface{}, error) {
	buff := bytes.NewBufferString("")
	_, err := io.Copy(buff, req.Body)
	if err != nil {
		logging.Error("GetReqBody copy req body error, request=%v, error=%s", req.Body, err)
		return nil, err
	}
	text := buff.String()
	req.Body = ioutil.NopCloser(strings.NewReader(text))

	err = json.Unmarshal([]byte(text), info)
	if err != nil {
		logging.Error("GetReqBody decode json body error, text=%s, error=%s", text, err)
		return nil, err
	}
	return info, nil
}

func GetLastParaFromURI(reqURI string) string {
	index := strings.LastIndex(reqURI, "/")
	if index == -1 {
		logging.Error("GetLastParaFromURI invalid reqURI:%s", reqURI)
		return ""
	}
	retStr := reqURI[index+1:]
	return retStr
}
